package org.apereo.cas.ticket.registry;


import org.apereo.cas.ticket.Ticket;
import org.apereo.cas.ticket.TicketGrantingTicket;

import java.time.ZonedDateTime;

/**
 * @author chenkh
 * @time 2022/1/19
 */
public abstract class AbstractTicketDelegator<T extends Ticket> implements Ticket {

    private static final long serialVersionUID = 1780193477774123440L;

    private final AbstractDistributedTicketRegistry ticketRegistry;

    private final T ticket;

    private final boolean callback;

    /**
     * Instantiates a new ticket delegator.
     *
     * @param ticketRegistry the ticket registry
     * @param ticket the ticket
     * @param callback the callback
     */
    protected AbstractTicketDelegator(final AbstractDistributedTicketRegistry ticketRegistry,
                                      final T ticket, final boolean callback) {
        this.ticketRegistry = ticketRegistry;
        this.ticket = ticket;
        this.callback = callback;
    }


    /**
     * Update ticket by the delegated registry.
     */
    protected void updateTicket() {
        this.ticketRegistry.updateTicket(this.ticket);
    }

    protected T getTicket() {
        return this.ticket;
    }

    @Override
    public final String getId() {
        return this.ticket.getId();
    }

    @Override
    public final boolean isExpired() {
        if (!callback) {
            return this.ticket.isExpired();
        }

        final TicketGrantingTicket t = getTicketGrantingTicket();

        return this.ticket.isExpired() || (t != null && t.isExpired());
    }

    public TicketGrantingTicket getTicketGrantingTicket() {
        final TicketGrantingTicket old = this.ticket.getTicketGrantingTicket();

        if (old == null || !callback) {
            return old;
        }
        return (TicketGrantingTicket) this.ticketRegistry.getTicket(old.getId(), Ticket.class);
    }

    @Override
    public final ZonedDateTime getCreationTime() {
        return this.ticket.getCreationTime();
    }

    @Override
    public final int getCountOfUses() {
        return this.ticket.getCountOfUses();
    }

    @Override
    public int hashCode() {
        return this.ticket.hashCode();
    }

    @Override
    public boolean equals(final Object o) {
        return this.ticket.equals(o);
    }

    @Override
    public int compareTo(final Ticket o) {
        return this.ticket.compareTo(o);
    }
}
